<template>
  <div v-if="!hidePreview" class="preview_video">
    <ul>
      <!--字符串类型-->
      <template v-if="isTypeString && urls[0]">
        <li @click="previewVideo(urls[0])">
          <svgicon class="preview_video__play" name="play"/>
          <img :src="urls[0].poster" alt="">
          <div
            v-if="!preview"
            class="preview_video__del"
            @click.stop="del()"
          >
            <i class="el-icon-delete"/>
          </div>
        </li>
      </template>
      <!--数组类型-->
      <template v-else>
        <li
          v-for="(item, inx) in urls"
          :key="item.poster"
          @click="previewVideo(item)"
        >
          <svgicon class="preview_video__play" name="play"/>
          <img :src="item.poster" alt="">
          <div
            v-if="!preview"
            class="preview_video__del"
            @click.stop="del(inx)"
          >
            <i class="el-icon-delete"/>
          </div>
        </li>
      </template>
    </ul>
  </div>
  <slot v-else/>
  <div
    v-if="showUpload && !preview"
    class="upload-video"
    :class="{disable: disable}"
    @click="handleClick"
  >
    <i class="upload-video__load el-icon-camera-solid"/>
    <input
      ref="elFile"
      class="upload-video__file"
      type="file"
      accept="video/*"
      @change="change"
    >
  </div>
  <VideoPlayer v-model="visible" :url="videoUrl"/>
</template>
<script lang="ts">
import { defineComponent, ref, PropType, watch, unref, computed } from 'vue'
import { ElMessage } from 'element-plus'
import VideoPlayer from './VideoPlayer'
import { isString, isArray } from '@/utils/is'
import { useOss, UrlItem } from './useOss'

export default defineComponent({
  name: 'UploadVideo',
  components: {
    VideoPlayer
  },
  props: {
    /** 类型可以是 Array | String ，如果是 string max 设置将为1 */
    modelValue: {
      type: [Array, String] as PropType<UrlItem[] | string>,
      default: () => []
    },
    /** 最大上传个数 */
    max: {
      type: Number as PropType<number>,
      default: 9
    },
    /** 视频大小 */
    size: {
      type: Number as PropType<number>,
      default: 1024 * 1024 * 50
    },
    /** 禁用上传项 */
    disable: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    /** 是否是preview */
    preview: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    /** 是否隐藏默认显示 */
    hidePreview: {
      type: Boolean as PropType<boolean>,
      default: false
    }
  },
  emits: ['change', 'update:modelValue'],
  setup(props, ctx) {
    const elFile = ref<Nullable<HTMLInputElement>>(null)
    const urls = ref<UrlItem[]>([])
    const OSS = useOss()
    const isTypeString = isString(props.modelValue || '')
    const visible = ref(false)
    const videoUrl = ref('')
    watch(
      () => props.modelValue,
      (val) => {
        if (isString(val)) {
          if (!val) urls.value = []
          else {
            urls.value = [{
              url: val as string,
              poster: getPoster(val as string)
            }]
          }
        } else if (isArray(val)) {
          urls.value = val
        } else {
          throw new Error('type error: Invalid type')
        }
      },
      { deep: true, immediate: true }
    )
    const showUpload = computed(() => {
      const val = unref(urls)
      if (isTypeString && val.length) {
        return false
      } else if (isArray(props.modelValue) && val.length >= props.max) {
        return false
      }
      return true
    })
    // 校验
    function check(files: FileList): boolean {
      const target = files[0]
      if (target.size > props.size) {
        let v = ''
        if (props.size < 1024) v = (props.size / 1024).toFixed(2) + 'KB'
        else v = (props.size / 1024 / 1024).toFixed(2) + 'M'
        ElMessage({
          message: `上传视频大小不可超出${v}哦~`,
          type: 'error'
        })
        return false
      }
      return true
    }

    function getPoster(url: string, width = 200, height?: number) {
      return `${url}?spm=qipa250&x-oss-process=video/snapshot,t_1000,w_${width},${height ? 't_' + height + ',' : ''}f_jpg,m_fast`
    }
    return {
      elFile,
      urls,
      showUpload,
      isTypeString,
      visible,
      videoUrl,
      handleClick: () => {
        if (elFile.value && !props.disable) {
          elFile.value.value = ''
          elFile.value.click()
        }
      },
      change: async(e: DragEvent) => {
        const files = (e.target as HTMLInputElement).files
        if (!files) return null
        if (!check(files)) return null
        OSS.uploadFile(files, {
          change: (url) => {
            // urls.value.push(url)
            const data = {
              url,
              poster: getPoster(url)
            }
            if (isTypeString) {
              urls.value = [data]
            } else {
              (urls.value as UrlItem[]).push(data)
            }
            const resData = isTypeString ? data.url : urls.value
            ctx.emit('update:modelValue', resData)
            ctx.emit('change', resData)
          }
        })
      },
      // 删除item
      del: (inx: number) => {
        // urls.value.splice(inx, 1)
        if (isTypeString) {
          urls.value = []
        } else {
          (urls.value as UrlItem[]).splice(inx, 1)
        }
      },
      // 预览视频
      previewVideo: (item: UrlItem) => {
        visible.value = true
        videoUrl.value = item.url
      }
    }
  }
})
</script>
<style lang="less" scoped>
.upload-video {
  display: inline-block;
  vertical-align: top;
  position: relative;
  border: 1px dashed;
  font-size: 0;
  border-radius: 5px;
  cursor: pointer;
  width: 100px;
  color: #d9d9d9;
  height: 100px;
  &:hover {
    color: #409eff;
  }
  &__load {
    position: absolute;
    font-size: 40px;
    transform: translate(-50%, -50%);
    top: 50%;
    left: 50%;
    color: #000;
  }
  &__file {
    overflow: hidden;
    display: none;
    outline: none;
    border: none;
    background: yellow;
  }
}
/** 视频 */
.preview_video {
  display: inline-block;
  vertical-align: top;
  ul {
    padding: 0px;
    margin: 0px;
    li {
      display: inline-block;
      margin-right: 10px;
      cursor: pointer;
      overflow: hidden;
      position: relative;
      width: 140px;
      height: 140px;
      border-radius: 5px;
      > img {
        object-fit: cover;
        height: 150px;
        width: 150px;
      }
      &:hover {
        .preview_video__del {
          bottom: 0px;
        }
      }
    }
  }
  @heiht: 40px;
  &__play {
    font-size: 3em;
    position: absolute;
    color: #fff;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
  &__del {
    position: absolute;
    bottom: -@heiht;
    width: 100%;
    height: @heiht;
    line-height: @heiht;
    background: #F56C6C;
    text-align: center;
    color: #fff;
    font-size: 16px;
    border-bottom-left-radius: 5px;
    border-bottom-right-radius: 5px;
    transition: bottom 0.3s;
  }
}
.disable {
  cursor: not-allowed !important;
  color: #d9d9d9 !important;
}
</style>
